package com.lph.niming.service;

import com.lph.niming.MyMain;
import com.lph.niming.pojo.Case;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;
import java.util.stream.Collectors;

/**
 * @auther: Wyz
 * @date: 2021/10/29 20:01
 * @return
 */
public class MyUtils {

    private static Scanner scanner = new Scanner(System.in);

    public List<String> getAttribute(Object T) {
        //拿到对象的Class
        Class<?> aClass = T.getClass();
        //获取对象中的字段
        Field[] declaredFields = aClass.getDeclaredFields();
        //拿到字段个数
        int length = declaredFields.length;
        List<String> list = new ArrayList<>();
        while (length-- > 0) {
            //把字段名放入到集合中
            list.add(declaredFields[length].getName());
        }
        return list;
    }

    /**
     * 删除类中的字段
     *
     * @param attribute: 类中所有字段名
     * @param fieldname: 要删除的字段名
     * @return void
     * @date 2021/10/29 23:10
     * @author wyz
     */
    public List<String> deleteField(List<String> attribute, String fieldname, List<Case> cases) {
        attribute.remove(fieldname);
        System.out.println("当前剩余属性为：" + attribute);
        System.out.println("是否还有其他标识属性（y：有、其他：无）");
        String next = scanner.next();
        if (next.equals("y")) {
            MyMain.identification(attribute, cases);
        }
        return attribute;
    }


    /**
     * 将一组数据平均分成n组
     *
     * @param source 要分组的数据源
     * @param n      平均分成n组
     * @param <T>
     * @return
     */
    public <T> List<List<T>>
    averageAssign(List<T> source, int n) {
        List<List<T>> result = new
                ArrayList<List<T>>();
        int remainder = source.size() % n;
        //(先计算出余数)
        int number = source.size() / n;
        //然后是商
        int offset = 0;//偏移量
        for (int i = 0; i < n; i++) {
            List<T> value = null;
            if (remainder > 0) {
                value = source.subList(i *
                        number + offset, (i + 1) * number +
                        offset + 1);
                remainder--;
                offset++;
            } else {
                value = source.subList(i *
                        number + offset, (i + 1) * number +
                        offset);
            }
            result.add(value);
        }
        return result;
    }

    /**
     * @param attribute:剩余的字段集合
     * @param lists: 分完组的集合
     * @param newCases: 用来存放且展示匿名后数据的集合
     * @return void
     * @date 2021/10/30 19:23
     * @author wyz
    */
    public void quasiIdentification(List<String> attribute, List<List<Case>> lists, List<Case> newCases) {
        System.out.println("除去标识符以及准准标识符后数据如下" + attribute);

        System.out.println("请输入准标识属性");
        //输入的准标识属性
        String next = scanner.next();
        switch (next) {
            case ("id"):
                //如果next是id执行下边代码
                //按照id匿名
                caseId(lists, attribute);
                //把需要展示的集合中数据清空
                newCases.removeAll(newCases);
                //展示匿名处理数据并询问是否还有其他准匿名属性的方法 下边一样就不在写了（下边代表case）
                handle(attribute, lists, newCases);
                //结束switch语句
                break;
            case ("age"):
                caseAge(lists, attribute);
                newCases.removeAll(newCases);
                handle(attribute, lists, newCases);
                break;
            case ("name"):
                caseName(lists, attribute);
                newCases.removeAll(newCases);
                handle(attribute, lists, newCases);
                break;
            case ("zipCode"):
                caseZipCode(lists, attribute);
                newCases.removeAll(newCases);
                handle(attribute, lists, newCases);
                break;
            case ("phone"):
                casePhone(lists, attribute);
                newCases.removeAll(newCases);
                handle(attribute, lists, newCases);
                break;
            case ("sex"):
                caseSex(lists, attribute);
                newCases.removeAll(newCases);
                handle(attribute, lists, newCases);
                break;
            case ("healthState"):
                caseHealthState(lists, attribute);
                newCases.removeAll(newCases);
                handle(attribute, lists, newCases);
                break;
            default:
                //如果输入的不是上边case里的数据
                System.out.println("请输入正确的字段名：" + attribute);
                //重新调用此方法
                quasiIdentification(attribute, lists, newCases);
                break;
        }
    }

    private void handle(List<String> attribute, List<List<Case>> lists, List<Case> newCases) {
        //把按照K分组后的数据拿出来放到newCases这个新集合中
        lists.forEach(s -> newCases.addAll(s));
        System.out.println("匿名处理后数据为下");
        //循环输出集合中的数据
        newCases.forEach(s -> System.out.println(s));
        System.out.println("是否还有其他准标识属性（y：有、其他：无）");
        String next = scanner.next();
        //如果输入的next是y
        if (next.equals("y")) {
            //调用匿名方法
            quasiIdentification(attribute, lists, newCases);
        }
        System.out.println("程序结束，谢谢使用");

    }

    private void caseId(List<List<Case>> lists, List<String> attribute) {
        //把剩余属性中的id删除
        attribute.remove("id");
        //循环分组后的数据
        for (int i = 0; i < lists.size(); i++) {
            //定义j=0，第二次循环进入j还是会重新赋值为0
            Integer j = 0;
            for (int k = 0; k < lists.get(i).size(); k++) {
                //循环相加第i组的id
                j += lists.get(i).get(k).getId();
            }
            //计算平均值
            int i1 = j / lists.get(i).size();
            //循环给这一组数据的id赋值
            lists.get(i).forEach(s -> s.setId(i1));
        }
    }

    private void caseName(List<List<Case>> lists, List<String> attribute) {
        //把剩余属性中的name删除
        attribute.remove("name");
        //循环分完组后的数据
        for (int i = 0; i < lists.size(); i++) {
            //拿到第i组数据
            List<Case> cases = lists.get(i);
            //根据Case中的name分组cases这个集合
            Map<String, List<Case>> collect = cases.stream().collect(Collectors.groupingBy(Case::getName));
            //如果分组后集合长度！=1 也就是>1
            if (collect.size() != 1) {
                //循环第i组集合
                for (int k = 0; k < cases.size(); k++) {
                    //拿到名字
                    String s = cases.get(k).getName();
                    //拿到名字的长度
                    int length = s.length();
                    //如果名字长度小于三，后边补*
                    if (length < 3) {
                        //重新赋值
                        cases.get(k).setName(s + "*");
                    }
                    //如果不小于三 取名字的前两位后边加*然后赋值
                    cases.get(k).setName(s.substring(0, 2) + "*");
                }
                //赋值完后重新分组（此时名字都是XX*这种格式）
                Map<String, List<Case>> collect1 = cases.stream().collect(Collectors.groupingBy(Case::getName));
                //如果分组后还是不等于1组
                if (collect1.size() != 1) {
                    for (int k = 0; k < cases.size(); k++) {
                        //拿到名字
                        String s = cases.get(k).getName();
                        //取名字的前一位后边加**然后赋值
                        cases.get(k).setName(s.substring(0, 1) + "**");
                    }
                    //赋值完后重新分组（此时名字都是X**这种格式）
                    Map<String, List<Case>> collect2 = cases.stream().collect(Collectors.groupingBy(Case::getName));
                    ////如果分组后还是不等于1组
                    if (collect2.size() != 1) {
                        for (int k = 0; k < cases.size(); k++) {
                            //把名字赋值为***  此时一定为一组，也就是说此组中的名字全部相同符合k匿名
                            cases.get(k).setName("***");
                        }
                    }
                }
            }
        }
    }

    private void caseAge(List<List<Case>> lists, List<String> attribute) {
        //把剩余属性中的age删除
        attribute.remove("age");
        for (int i = 0; i < lists.size(); i++) {
            //拿到第i组的数据
            List<Case> cases = lists.get(i);
            for (int j = 0; j < cases.size(); j++) {
                //如果年龄在0~24之间赋值为0~24
                if (Integer.valueOf(cases.get(j).getAge()) < 25) {
                    cases.get(j).setAge("0~24");
                } else if (Integer.valueOf(cases.get(j).getAge()) < 50) {
                    //如果年龄在25~49之间赋值为25~49
                    cases.get(j).setAge("25~49");
                } else if (Integer.valueOf(cases.get(j).getAge()) < 75) {
                    //如果年龄在50~74之间赋值为50~74
                    cases.get(j).setAge("50~74");
                } else if (Integer.valueOf(cases.get(j).getAge()) < 100) {
                    //如果年龄在50~74之间赋值为50~74
                    cases.get(j).setAge("75~100");
                } else {
                    //剩余的为大于100
                    cases.get(j).setAge(">100");
                }

            }
            //按照年龄分组（此时数据有五种可能（0~24，25~49、50~74、75~100，>100））
            Map<String, List<Case>> collect = cases.stream().collect(Collectors.groupingBy(Case::getAge));
            //如果分组后不为1组 也就是大于1组
            if (collect.size() != 1) {
                for (int j = 0; j < cases.size(); j++) {
                    //如果年龄为0~24或者25~49
                    if (cases.get(j).getAge().equals("0~24") || cases.get(j).getAge().equals("25~49")) {
                        //把年龄重新赋值为0~49
                        cases.get(j).setAge("0~49");
                    } else if (cases.get(j).getAge().equals("50~74") || cases.get(j).getAge().equals("75~100")) {
                        //如果年龄为50~74或者75~100 把年龄重新赋值为50~100
                        cases.get(j).setAge("50~100");
                    } else {
                        //剩余的为大于100
                        cases.get(j).setAge(">100");
                    }
                }
            }
            //按照年龄分组（此时数据有五种可能（0~49、50~100，>100））
            Map<String, List<Case>> collect1 = cases.stream().collect(Collectors.groupingBy(Case::getAge));
            //如果分组后不为1组 也就是大于1组
            if (collect1.size() != 1) {
                for (int j = 0; j < cases.size(); j++) {
                    //如果年龄为>100 赋值为》100
                    if (cases.get(j).getAge().equals(">100")) {
                        cases.get(j).setAge(">100");
                    } else {
                        //否则赋值为0~100
                        cases.get(j).setAge("0~100");
                    }
                }
            }
            //按照年龄分组（此时数据有五种可能（0~100，>100））
            Map<String, List<Case>> collect2 = cases.stream().collect(Collectors.groupingBy(Case::getAge));
            //如果还不是一组
            if (collect2.size() != 1) {
                //把所有的年龄都赋值为》0
                for (int j = 0; j < cases.size(); j++) {
                    cases.get(j).setAge(">0");
                }
            }

        }
    }

    private void caseZipCode(List<List<Case>> lists, List<String> attribute) {
        //把剩余属性中的zipCode删除
        attribute.remove("zipCode");
        for (int i = 0; i < lists.size(); i++) {
            //拿到第i组的数据
            List<Case> cases = lists.get(i);
            //把第i组数据按照邮编进行分组
            Map<String, List<Case>> collect1 = cases.stream().collect(Collectors.groupingBy(Case::getZipCode));
            //如果分组后的数据不是一组
            if (collect1.size() != 1) {
                //把邮编的最后一位变*  453400
                cases.forEach(s->s.setZipCode(s.getZipCode().substring(0,5)+"*"));
            }
            //再次分组
            Map<String, List<Case>> collect2 = cases.stream().collect(Collectors.groupingBy(Case::getZipCode));
            if (collect2.size() != 1) {
                //倒数第二位变*
                cases.forEach(s->s.setZipCode(s.getZipCode().substring(0,4)+"**"));
            }
            //再次分组
            Map<String, List<Case>> collect3 = cases.stream().collect(Collectors.groupingBy(Case::getZipCode));
            if (collect3.size() != 1) {
                //倒数第三位变* 下边就不写了
                cases.forEach(s->s.setZipCode(s.getZipCode().substring(0,3)+"***"));
            }
            Map<String, List<Case>> collect4 = cases.stream().collect(Collectors.groupingBy(Case::getZipCode));
            if (collect4.size() != 1) {
                cases.forEach(s->s.setZipCode(s.getZipCode().substring(0,2)+"****"));
            }
            Map<String, List<Case>> collect5 = cases.stream().collect(Collectors.groupingBy(Case::getZipCode));
            if (collect5.size() != 1) {
                cases.forEach(s->s.setZipCode(s.getZipCode().substring(0,1)+"*****"));
            }
            Map<String, List<Case>> collect6 = cases.stream().collect(Collectors.groupingBy(Case::getZipCode));
            if (collect6.size() != 1) {
                cases.forEach(s->s.setZipCode("******"));
            }
        }
    }

    private void casePhone(List<List<Case>> lists, List<String> attribute) {
        //把剩余属性的手机号删除
        attribute.remove("phone");
        for (int i = 0; i < lists.size(); i++) {
            //拿出分组后的第i组数据
            List<Case> cases = lists.get(i);
            //因为手机号有11为，从最后一位比较我闲麻烦 所以就留了手机号的前三位后八位改为了*
            cases.forEach(s->s.setPhone(s.getPhone().substring(0,3)+"********"));
            //按照后八位为*的手机号分组
            Map<String, List<Case>> collect1 = cases.stream().collect(Collectors.groupingBy(Case::getPhone));
            //如果分组后不是1组
            if (collect1.size() != 1) {
                //后九位改成*
                cases.forEach(s->s.setPhone(s.getPhone().substring(0,2)+"*********"));
            }
            //按照后九位为*的手机号分组
            Map<String, List<Case>> collect2 = cases.stream().collect(Collectors.groupingBy(Case::getPhone));
            //如果分组后不是1组
            if (collect2.size() != 1) {
                ////后十位改成*
                cases.forEach(s->s.setPhone(s.getPhone().substring(0,1)+"**********"));
            }
            //按照后十位为*的手机号分组
            Map<String, List<Case>> collect3 = cases.stream().collect(Collectors.groupingBy(Case::getPhone));
            if (collect3.size() != 1) {
                //全部改成*
                cases.forEach(s->s.setPhone("***********"));
            }
        }
    }

    private void caseSex(List<List<Case>> lists, List<String> attribute) {
        attribute.remove("sex");
        for (int i = 0; i < lists.size(); i++) {
            List<Case> cases = lists.get(i);
            //按照性别分组
            Map<String, List<Case>> collect3 = cases.stream().collect(Collectors.groupingBy(Case::getSex));
            //如果分组后不是1组
            if (collect3.size() != 1) {
                //把性别改成*
                cases.forEach(s->s.setSex("*"));
            }
        }
    }

    private void caseHealthState(List<List<Case>> lists, List<String> attribute) {
        attribute.remove("healthState");
    }
}
